package org.bigbluebutton.web.services.turn;
import java.security.SignatureException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class TurnServer {
private final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
private final String COLON = ":";
private final String secretKey;
private final String url;
private final int ttl;
public TurnServer(String secretKey, String url, int ttl) {
this.secretKey = secretKey;
this.url = url;
this.ttl = ttl;
}
public TurnEntry generatePasswordFor(String userId) {
TurnEntry turn = null;
try {
long expiryTime = System.currentTimeMillis() / 1000 + ttl;
String username = expiryTime + COLON + userId;
String password = calculateRFC2104HMAC(username, secretKey);
turn = new TurnEntry(username, password, ttl, url);
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return turn;
}
/**
* Computes RFC 2104-compliant HMAC signature.
* * @param data
* The data to be signed.
* @param key
* The signing key.
* @return
* The Base64-encoded RFC 2104-compliant HMAC signature.
* @throws
* java.security.SignatureException when signature generation fails
*/
private String calculateRFC2104HMAC(String data, String key)
throws java.security.SignatureException
{
String result;
try {
// get an hmac_sha1 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
// get an hmac_sha1 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
// base64-encode the hmac
result = new String(Base64.encodeBase64(rawHmac));
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
}